%{
	enum tokens {
			W_PROGRAM, W_FUNCTION, W_SUBROUTINE, W_END, W_INTEGER,
			W_REAL, W_DOUBLE, W_COMPLEX, W_LOGICAL, W_CHARACTER,
			W_IF, W_THEN, W_ELSE, W_ENDIF, W_DO,
			W_CONTINUE, W_GOTO, W_STOP, W_RETURN, W_CALL,
			W_PARAMETER, OP_NOT, OP_PLUS, OP_MINUS, OP_MULT,
			OP_DIV, OP_EXP, OP_GT, OP_GE, OP_EQ,
			OP_NE, OP_LT, OP_LE, OP_AND, OP_OR,
			LIT_TRUE, LIT_FALSE, IDENTIFIER, LIT_INTEGER, LIT_FLOAT,
			LIT_DOUBLE, LIT_COMPLEX, LIT_CHARACTER,
			OPEN_PAREN, CLOSE_PAREN
	};
%}

DIGIT    [0-9]
ID       [A-Z][A-Z0-9]*


%%


PROGRAM.*				yyless( 7); { return W_PROGRAM; 		}
FUNCTION.*			yyless( 8); { return W_FUNCTION; 		}
SUBROUTINE.*		yyless(10); { return W_SUBROUTINE; 	}
END													{ return W_END; 				}
INTEGER.*				yyless( 7); { return W_INTEGER; 		}
REAL.*					yyless( 4); { return W_REAL; 				}
DOUBLE.*				yyless( 6); { return W_DOUBLE; 			}
COMPLEX.*				yyless( 6); { return W_COMPLEX; 		}
LOGICAL.*				yyless( 7); { return W_LOGICAL; 		}
CHARACTER.*			yyless( 9); { return W_CHARACTER; 	}
IF.*						yyless( 2); { return W_IF; 					}
THEN.*					yyless( 4); { return W_THEN; 				}
ELSE.*					yyless( 4); { return W_ELSE; 				}
ENDIF.*					yyless( 5); { return W_ENDIF; 			}
DO.*						yyless( 2); { return W_DO; 					}
CONTINUE.*			yyless( 8); { return W_CONTINUE; 		}
GOTO.*					yyless( 4); { return W_GOTO; 				}
STOP.*					yyless( 4); { return W_STOP; 				}
RETURN.*				yyless( 6); { return W_RETURN; 			}
CALL.*					yyless( 4); { return W_CALL; 				}
PARAMETER.*			yyless( 9); { return W_PARAMETER; 	}


\.NOT\.											{ return OP_NOT; 				}
\.GT\.											{ return OP_GT; 				}
\.GE\.											{ return OP_GE; 				}
\.EQ\.											{ return OP_EQ; 				}
\.NE\.											{ return OP_NE; 				}
\.LT\.											{ return OP_LT; 				}
\.LE\.											{ return OP_LE; 				}
\.AND\.											{ return OP_AND; 				}
\.OR\.											{ return OP_OR; 				}

\+													{ return OP_PLUS; 			}
\*[^*]					yyless( 1);	{ return OP_MULT; 			}
\*{2}												{ return OP_EXP; 				}
-														{ return OP_MINUS;			}
\/													{ return OP_DIV; 				}

\(													{ return OPEN_PAREN;		}
\)													{ return CLOSE_PAREN;		}

\.TRUE\.																		{ return LIT_TRUE; 			}
\.FALSE\. 																	{ return LIT_FALSE; 		}
[\+-]?{DIGIT}+ 															{ return LIT_INTEGER; 	}
[+-]?{DIGIT}+\.{DIGIT}+(E[+-]?{DIGIT}+)?		{ return LIT_FLOAT; 		}
[+-]?{DIGIT}+\.{DIGIT}+D[+-]?{DIGIT}+ 			{ return LIT_DOUBLE; 		}
'[^'\n]*' 																	{ return LIT_CHARACTER; }
{ID} 																				{ return IDENTIFIER; 		}

%%

main() {
	while(1) {
		int a = yylex();
		printf("%d\n", a);
	}
}
